package server.connector.http;

import server.util.Enumerator;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class HttpRequestImpl extends HttpRequestBase implements HttpServletRequest {
    protected static final ArrayList<String> emptyList = new ArrayList<>();
    protected static Locale defaultLocale = Locale.getDefault();
    protected SimpleDateFormat formats[] = {
            new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
            new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
            new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
    };

    //返回请求发过来的所有Cookie,没有Cookie返回null
    @Override
    public Cookie[] getCookies() {
        synchronized (cookies) {
            if (cookies.size() > 0) {
                return (Cookie[]) cookies.toArray();
            }
        }
        return null;
    }


    //将给定名称请求头的值转换为时间戳返回,未找到值返回-1,转换失败抛出IllegalArgumentException异常
    @Override
    public long getDateHeader(String name) {
        String value = getHeader(name);
        if (value == null)
            return -1;
        for (SimpleDateFormat format : formats) {
            try {
                Date date = format.parse(value);
                return date.getTime();
            } catch (ParseException e) {

            }
        }
        throw new IllegalArgumentException("无法解析的时间格式:[" + value + "]");
    }

    //返回给定名称请求头的值(大小写不敏感),未找到返回null
    @Override
    public String getHeader(String name) {
        name = name.toLowerCase();
        synchronized (headers) {
            ArrayList<String> values = headers.get(name);
            if(values == null || values.size() <= 0) {
                return null;
            }
            return values.get(0);
        }
    }


    //返回name对应请求头的所有值
    @Override
    public Enumeration<String> getHeaders(String name) {
        name = name.toLowerCase();
        ArrayList<String> values = null;
        synchronized (headers) {
             values = headers.get(name);
        }
        if (values == null)
            values = emptyList;
        return new Enumerator<String>(values);
    }

    //返回所有的请求头名称
    @Override
    public Enumeration<String> getHeaderNames() {
        synchronized (headers) {
            return new Enumerator<String>(headers.keySet());
        }
    }

    //将给定名称请求头的值转换为整数返回,未找到值返回-1,转换失败抛出NumberFormatException异常
    @Override
    public int getIntHeader(String name) {
        String value = getHeader(name);
        if (value == null)
            return -1;
        return Integer.parseInt(value);
    }

    //返回请求方法
    @Override
    public String getMethod() {
        return this.method;
    }

    //返回请求URI
    @Override
    public String getRequestURI() {
        return this.requestURI;
    }

    //返回查询字符串
    @Override
    public String getQueryString() {
        return this.queryString;
    }

    //返回sessionID
    @Override
    public String getRequestedSessionId() {
        return this.requestedSessionId;
    }

    //返回协议版本
    @Override
    public String getProtocol() {
        return this.protocol;
    }

    //返回内容长度
    @Override
    public int getContentLength() {
        return this.contentLength;
    }

    //返回内容long型长度
    @Override
    public long getContentLengthLong() {
        return (long)this.contentLength;
    }

    //返回内容MINE类型
    @Override
    public String getContentType() {
        return this.contentType;
    }

    //返回字符集编码
    @Override
    public String getCharacterEncoding() {
        return this.characterEncoding;
    }

    //设置字符集编码,如果设置的编码格式不支持,抛出UnsupportedEncodingException异常
    @Override
    public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
        byte[] buffer = new byte[1];
        buffer[0] = 'a';
        //测试是否支持该字符集
        String s = new String(buffer, env);
        this.characterEncoding = env;
    }

    //返回客户端IP地址
    @Override
    public String getRemoteAddr() {
        return inet.getHostAddress();
    }

    //返回客户端主机名
    @Override
    public String getRemoteHost() {
        if(connector.isEnableLookups())
            return inet.getHostName();
        else
            return getRemoteAddr();
    }

    //返回客户端端口号
    @Override
    public int getRemotePort() {
        return socket.getPort();
    }

    //返回name对应的属性值,没找到返回null
    @Override
    public Object getAttribute(String name) {
        synchronized (attributes) {
            return attributes.get(name);
        }
    }

    //返回所有属性名
    @Override
    public Enumeration<String> getAttributeNames() {
        synchronized (attributes) {
            return new Enumerator<String>(attributes.keySet());
        }
    }
    //设置属性值 name为null抛出IllegalArgumentException异常
    @Override
    public void setAttribute(String name, Object o) {
        //属性名不能为null
        if (name == null) {
            throw new IllegalArgumentException("属性名不能为null");
        }
        //值为null没有意义
        if (o == null) {
            removeAttribute(name);
            return;
        }
        synchronized (attributes) {
            attributes.put(name, o);
        }
    }

    //根据name删除属性
    @Override
    public void removeAttribute(String name) {
        synchronized (attributes) {
            attributes.remove(name);
        }
    }

    //获取封装后的输入流(隐藏对端分块发送的处理细节)
    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (this.reader != null)
            throw new IllegalStateException("getReader()方法已经被调用过");
        if (this.stream == null)
            this.stream = createInputStream();
        return this.stream;
    }

    //获取封装后的Reader(隐藏对端分块发送的处理细节,按指定字符集进行字节转字符)
    @Override
    public BufferedReader getReader() throws IOException {
        if (stream != null)
            throw new IllegalStateException("getStream方法已经被调用过");
        if (reader == null) {
            String encoding = getCharacterEncoding();
            if (encoding == null)
                encoding = Constants.DEFAULT_REQUEST_ENCODING;
            InputStreamReader isr = new InputStreamReader(createInputStream(), encoding);
            reader = new BufferedReader(isr);
        }
        return reader;
    }

    //根据参数名返回参数值,未找到时返回null
    @Override
    public String getParameter(String name) {
        parseParameters();
        //parameters上锁后Servlet程序只能读不能修改,线程安全,不需要加锁
        String[] values = parameters.get(name);
        if (values == null || values.length <= 0)
            return null;
        return values[0];
    }

    //返回所有参数名
    @Override
    public Enumeration<String> getParameterNames() {
        parseParameters();
        return new Enumerator<String>(parameters.keySet());
    }

    //根据参数名返回所有参数值,未找到时返回null
    @Override
    public String[] getParameterValues(String name) {
        parseParameters();
        String[] values = parameters.get(name);
        if (values == null)
            return null;
        //避免Servlet程序修改参数值
        return values.clone();
    }

    //返回存放参数的map
    @Override
    public Map<String, String[]> getParameterMap() {
        parseParameters();
        return parameters;
    }

    //返回使用的协议
    @Override
    public String getScheme() {
        return this.scheme;
    }

    //返回请求的服务器主机名(url中的主机名)
    @Override
    public String getServerName() {
        return this.serverName;
    }

    //返回请求的服务器端口(url中的端口)
    @Override
    public int getServerPort() {
        return this.serverPort;
    }

    //返回url
    @Override
    public StringBuffer getRequestURL() {
        StringBuffer url = new StringBuffer();
        String scheme = getScheme();
        int serverPort = getServerPort();
        //http协议默认端口是80,https协议默认端口是443
        if (serverPort < 0) {
            if ("http".equals(scheme))
                serverPort = 80;
            else if ("https".equals(scheme))
                serverPort = 443;
        }
        url.append(scheme);
        url.append("://");
        url.append(getServerName());
        if (("http".equals(scheme) && serverPort != 80) ||
                ("https".equals(scheme) && serverPort != 443)
        ) {
            url.append(":");
            url.append(serverPort);
        }
        url.append(getRequestURI());
        return url;
    }


    //SessionId是否来自Cookie
    @Override
    public boolean isRequestedSessionIdFromCookie() {
        if (requestedSessionId == null)
            return false;
        return requestedSessionIdFromCookie;
    }

    //sessionID来自url?
    @Override
    public boolean isRequestedSessionIdFromURL() {
        if (requestedSessionId == null)
            return false;
        return requestedSessionIdFromURL;
    }

    //sessionID来自url?
    @Override
    public boolean isRequestedSessionIdFromUrl() {
        return isRequestedSessionIdFromURL();
    }

    //安全连接?
    @Override
    public boolean isSecure() {
        return this.secure;
    }

    //返回accept-Language头接受语言权重最大的Locale对象,如果客户端未指明accept-Language,返回默认Locale
    @Override
    public Locale getLocale() {
        synchronized (locales) {
            if (locales != null && locales.size() > 0)
                return locales.get(0);
        }
        return defaultLocale;
    }

    //返回accept-Language头接受语言权重按降序排序的Locale对象,如果客户端未指明accept-Language,返回默认Locale
    @Override
    public Enumeration<Locale> getLocales() {
        synchronized (locales) {
            if (locales != null && locales.size() > 0)
                return new Enumerator<Locale>(locales);
        }
        ArrayList<Locale> list = new ArrayList<>();
        list.add(defaultLocale);
        return new Enumerator<Locale>(list);
    }

    //获取实际服务器的主机名
    @Override
    public String getLocalName() {
        return connector.getLocalName();
    }

    //获取实际服务器的IP地址
    @Override
    public String getLocalAddr() {
        return connector.getLocalAddr();
    }

    //获取实际服务器的端口号
    @Override
    public int getLocalPort() {
        return connector.getLocalPort();
    }
    //上面是OK的方法--------------------------------------------------------------------------------------------------------
    @Override
    public String getPathInfo() {
        return null;
    }

    @Override
    public String getPathTranslated() {
        return null;
    }

    @Override
    public String getContextPath() {
        return null;
    }


    @Override
    public String getRemoteUser() {
        return null;
    }

    @Override
    public boolean isUserInRole(String role) {
        return false;
    }

    @Override
    public Principal getUserPrincipal() {
        return null;
    }


    @Override
    public String getServletPath() {
        return null;
    }

    @Override
    public HttpSession getSession(boolean create) {
        return null;
    }

    @Override
    public HttpSession getSession() {
        return null;
    }

    @Override
    public String changeSessionId() {
        return null;
    }

    @Override
    public boolean isRequestedSessionIdValid() {
        return false;
    }


    @Override
    public RequestDispatcher getRequestDispatcher(String path) {
        return null;
    }

    @Override
    public String getRealPath(String path) {
        return null;
    }

    @Override
    public ServletContext getServletContext() {
        return null;
    }


    //不懂的-------------------------------------------------------------------------------
    @Override
    public String getAuthType() {
        return this.authType;
    }

    //暂不实现-------------------------------------------------------------------------------
    @Override
    public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
        return false;
    }

    @Override
    public void login(String username, String password) throws ServletException {

    }

    @Override
    public void logout() throws ServletException {

    }

    @Override
    public Collection<Part> getParts() throws IOException, ServletException {
        return null;
    }

    @Override
    public Part getPart(String name) throws IOException, ServletException {
        return null;
    }

    @Override
    public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException {
        return null;
    }
    @Override
    public AsyncContext startAsync() throws IllegalStateException {
        return null;
    }

    @Override
    public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException {
        return null;
    }

    @Override
    public boolean isAsyncStarted() {
        return false;
    }

    @Override
    public boolean isAsyncSupported() {
        return false;
    }

    @Override
    public AsyncContext getAsyncContext() {
        return null;
    }

    @Override
    public DispatcherType getDispatcherType() {
        return null;
    }


}
